///////////////////////////////////////////////////////////////////////////////
//
// Licensed under the MIT License
//
// Copyright (c) 2010 Chris Colinsky
// All Rights Reserved
//
// version	0.5
// http://code.google.com/p/sugarcookie/
// http://code.google.com/p/sugarcookie/wiki/License
//
////////////////////////////////////////////////////////////////////////////////

package sugarcookie.file {
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
	
	import mx.logging.ILogger;
	import mx.logging.Log;
	
	import sugarcookie.error.ApplicationError;
	import sugarcookie.events.GenericEvent;
	
	/**
	 * Proxy to the URLLoader class
	 */
	public class DataLoader extends EventDispatcher {
		private var _uri:String;
		private var _urlLoader:URLLoader;
		private var _requestData:Object;
		private var _log:ILogger;
		
		public static const ERROR:String = "onError";
		public static const STATUS:String = "onStatus";
		public static const COMPLETE:String = "onComplete";
		
		public function DataLoader(uri:String=null,requestData:Object=null) {
			_log = Log.getLogger("sugarcookie.file.DataLoader");
			
			_uri = uri;
			
			_requestData = requestData;
			
			_urlLoader = new URLLoader();
			_urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorListener);
			_urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorListener);
			_urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, statusListener);
			_urlLoader.addEventListener(ProgressEvent.PROGRESS, progressListener);
			_urlLoader.addEventListener(Event.COMPLETE, completeListener);
		}
		
		public function get uri():String { return _uri; }
		public function set uri(uri:String):void { _uri = uri; }
		
		public function load():void {
			_log.debug("Loading: "+_uri);
			
			if (_uri==null) throw new ApplicationError("No source URI has been defined!");
			
			var request:URLRequest = new URLRequest(_uri);
			if (_requestData!=null) {
				var vars:URLVariables = new URLVariables();
				for (var i:String in _requestData) vars[i] = _requestData[i];
				request.data = vars;
			}
			_urlLoader.load(request);
		}
		
		public function get data():* {
			return _urlLoader.data;
		}
		
		private function ioErrorListener(e:IOErrorEvent):void {
			_log.error(e.text);
			dispatchEvent(new GenericEvent(ERROR,false,false,e.text,false));
		}
		
		private function securityErrorListener(e:SecurityErrorEvent):void {
			_log.error(e.text);
			dispatchEvent(new GenericEvent(ERROR,false,false,e.text,false));
		}
		
		private function statusListener(e:HTTPStatusEvent):void {
			//for more detailed explainations of these status codes see: ftp://ftp.isi.edu/in-notes/rfc2616.txt
			var _status_text:String;
			var _isError:Boolean = true;
			switch (e.status) {
				case 0:
					_status_text = "Unable to determine status.";
					_isError = false;
					break;
				case 100:
					_status_text = "Continue";
					_isError = false;
					break;
				case 101:
					_status_text = "Switching Protocols";
					_isError = false;
					break;
				case 200:
					_status_text = "OK";
					_isError = false;
					break;
				case 201:
					_status_text = "Created";
					_isError = false;
					break;
				case 202:
					_status_text = "Accepted";
					_isError = false;
					break;
				case 203:
					_status_text = "Non-Authoritative Information";
					_isError = false;
					break;
				case 204:
					_status_text = "No Content";
					_isError = false;
					break;
				case 205:
					_status_text = "Reset Content";
					_isError = false;
					break;
				case 206:
					_status_text = "Partial Content";
					_isError = false;
					break;
				case 300:
					_status_text = "Multiple Choices";
					_isError = false;
					break;
				case 301:
					_status_text = "Moved Permanently";
					break;
				case 302:
					_status_text = "Found";
					break;
				case 303:
					_status_text = "See Other";
					break;
				case 304:
					_status_text = "Not Modified";
					break;
				case 305:
					_status_text = "Use Proxy";
					break;
				case 307:
					_status_text = "Temporary Redirect";
					break;
				case 400:
					_status_text = "Bad Request";
					break;
				case 401:
					_status_text = "Unauthorized";
					break;
				case 403:
					_status_text = "Forbidden";
					break;
				case 404:
					_status_text = "File Not Found";
					break;
				case 405:
					_status_text = "Method Not Allowed";
					break;
				case 406:
					_status_text = "Not Acceptable";
					break;
				case 407:
					_status_text = "Proxy Authentication Required";
					break;
				case 408:
					_status_text = "Request Timeout";
					break;
				case 409:
					_status_text = "Conflict";
					break;
				case 410:
					_status_text = "Gone";
					break;
				case 411:
					_status_text = "Length Required";
					break;
				case 412:
					_status_text = "Precondition Failed";
					break;
				case 413:
					_status_text = "Request Entity Too Large";
					break;
				case 414:
					_status_text = "Request-URI Too Long";
					break;
				case 415:
					_status_text = "Unsupported Media Type";
					break;
				case 416:
					_status_text = "Requested Range Not Satisfiable";
					break;
				case 417:
					_status_text = "Expectation Failed";
					break;
				case 500:
					_status_text = "Internal Server Error";
					break;
				case 501:
					_status_text = "Not Implemented";
					break;
				case 502:
					_status_text = "Bad Gateway";
					break;
				case 503:
					_status_text = "Service Unavailable";
					break;
				case 504:
					_status_text = "Gateway Timeout";
					break;
				case 505:
					_status_text = "HTTP Version Not Supported";
					break;
				default:
					_status_text = "Status Code Is Not Recognized";
					break;
			}
			
			_log.debug("Status Code: "+e.status+", Description: "+_status_text);
			if (_isError) dispatchEvent(new GenericEvent(ERROR,false,false,String("Status Code: "+e.status+", Description: "+_status_text),false));
			else dispatchEvent(new GenericEvent(STATUS,false,false,String("Status Code: "+e.status+", Description: "+_status_text),false));
		}
		
		private function progressListener(e:ProgressEvent):void {
			var _perc:int = (e.bytesLoaded/e.bytesTotal)*100;
			dispatchEvent(new GenericEvent(STATUS,false,false,_perc,false));
		}
		
		private function completeListener(e:Event):void {
			_log.debug("Data load is complete.");
			dispatchEvent(new GenericEvent(COMPLETE,false,false,"complete",false));
		}
	}
}